//
//  JYVerifyRegEx.m
//  MYCCBRegisterSubAccount
//
//  Created by 应明顺 on 2018/7/4.
//  Copyright © 2018年 JackYing. All rights reserved.
//

#import "JYVerifyRegEx.h"

@interface JYVerifyRegEx ()

/// 每Reverse一次消耗一定性能，而输入框每输入一个字符就需要Reverse一次，必将消耗更多的性能
/// 所以将曾经遇到过的regEx对应的reverse缓存起来，用于计算chartLengthCaChe，避免不必要的消耗
@property (nonatomic, strong) NSCache <NSString *, NSString *> *reverseRegExCaChe;

/// 每Reverse一次消耗一定性能，而输入框每输入一个字符就需要Reverse一次，必将消耗更多的性能
/// 所以将曾经遇到过的regEx对应的simpleChart缓存起来，避免不必要的消耗
@property (nonatomic, strong) NSCache <NSString *, NSString *> *simpleRegExCaChe;

/// 每次截取字符/或反转字符串时会消耗一定性能，而输入框每输入一个字符执行一次，必将消耗更多的性能
/// 所以将曾经使计算过的contentSize缓存起来，避免不必要的消耗
@property (nonatomic, strong) NSCache <NSString *, NSValue *> *contentSizeCaChe;

/// 每生成一个NSRegularExpression实例会消耗一定性能，而输入框每输入一个字符就生成一个NSRegularExpression，必将消耗更多的性能
/// 所以将曾经使用过的NSRegularExpression缓存起来，避免不必要的消耗
@property (nonatomic, strong) NSCache <NSString *, NSRegularExpression *> *regExCaChe;

@end

@implementation JYVerifyRegEx

+ (JYVerifyRegEx *)shareInstance {
    static JYVerifyRegEx *shareInstance = nil;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        shareInstance = [[JYVerifyRegEx alloc] init];
    });
    return shareInstance;
}

- (instancetype)init
{
    self = [super init];
    if (self) {
        
        _regExCaChe = [[NSCache alloc] init];
        _simpleRegExCaChe = [[NSCache alloc] init];
        _contentSizeCaChe = [[NSCache alloc] init];
        _reverseRegExCaChe = [[NSCache alloc] init];
        
        _regExCaChe.totalCostLimit = _regExCaChe.countLimit = 3;
        _simpleRegExCaChe.totalCostLimit = _simpleRegExCaChe.countLimit = 3;
        _contentSizeCaChe.totalCostLimit = _contentSizeCaChe.countLimit  = 3;
        _reverseRegExCaChe.totalCostLimit = _reverseRegExCaChe.countLimit = 3;
    }
    return self;
}


/**
 提取正则中的简单限制字符，即最核心的[]内的字符集

 @param regEx 原始正则表达式
 @return 截取后的核心表达式
 */
+ (NSString *)simpleChartVerifyRegEx:(NSString *)regEx {
    
    NSString *orgRegex = regEx;
    NSString *simpleRegEx = [JYVerifyRegEx.shareInstance.simpleRegExCaChe objectForKey:orgRegex];
    if (simpleRegEx != nil && simpleRegEx.length > 1) {
        return simpleRegEx;
    }
    
    NSString *reverseRegEx = [JYVerifyRegEx.shareInstance p_reverseRegExCache:orgRegex];
    
    // 2.后在倒置的基础上截取“] [”之间的字符集
    NSString *contentString = nil;
    contentString = [reverseRegEx substringFromIndex:[reverseRegEx rangeOfString:@"]"].location];
    contentString = [contentString substringToIndex:[contentString rangeOfString:@"["].location + 1];
    
    // 3.最后再对截取出来的部分全部倒置，
    NSMutableString *newRegex = [NSMutableString stringWithCapacity:contentString.length];
    [contentString
     enumerateSubstringsInRange:NSMakeRange(0, contentString.length)
     options:(NSStringEnumerationByComposedCharacterSequences | NSStringEnumerationReverse)
     usingBlock:^(NSString * _Nullable substring, NSRange substringRange, NSRange enclosingRange, BOOL * _Nonnull stop) {
         
         [newRegex appendString:substring];
     }];
    
    [newRegex insertString:@"^" atIndex:0];
    [newRegex appendString:@"*$"];
    [JYVerifyRegEx.shareInstance.simpleRegExCaChe setObject:[newRegex copy] forKey:orgRegex];
    
    return [newRegex copy];
}

+ (CGSize)contentSizeOfRegEx:(NSString *)regEx {

    NSValue *sizeValue = [JYVerifyRegEx.shareInstance.contentSizeCaChe objectForKey:regEx];
    if (sizeValue != nil) {
        return [sizeValue CGSizeValue];
    }
    
    NSString *reverseRegEx = [JYVerifyRegEx.shareInstance p_reverseRegExCache:regEx];
    // "[]*"
    if ([[reverseRegEx substringWithRange:NSMakeRange(1, 1)] isEqualToString:@"*"]) {
        
        sizeValue = [NSValue valueWithCGSize:CGSizeMake(0, NSIntegerMax)];
        [JYVerifyRegEx.shareInstance.contentSizeCaChe setObject:sizeValue forKey:regEx];
        return [sizeValue CGSizeValue];
    }
    // "[]+"
    else if ([[reverseRegEx substringWithRange:NSMakeRange(1, 1)] isEqualToString:@"+"]) {
        
        sizeValue = [NSValue valueWithCGSize:CGSizeMake(1, NSIntegerMax)];
        [JYVerifyRegEx.shareInstance.contentSizeCaChe setObject:sizeValue forKey:regEx];
        return [sizeValue CGSizeValue];
    }
    // "[]{n,m}"
    else {
        
        // 2.后在倒置的基础上截取“} {”之间的字符集
        NSString *sizeString = nil;
        sizeString = [reverseRegEx substringFromIndex:[reverseRegEx rangeOfString:@"}"].location+1];
        sizeString = [sizeString substringToIndex:[sizeString rangeOfString:@"{"].location];
        // 3.最后再对截取出来的部分全部倒置，避免多位数的情况
        NSMutableString *newRegex = [NSMutableString stringWithCapacity:sizeString.length];
        [sizeString
         enumerateSubstringsInRange:NSMakeRange(0, sizeString.length)
         options:(NSStringEnumerationByComposedCharacterSequences | NSStringEnumerationReverse)
         usingBlock:^(NSString * _Nullable substring, NSRange substringRange, NSRange enclosingRange, BOOL * _Nonnull stop) {
             [newRegex appendString:substring];
         }];
        // 拆分成数组，前面为小值W，后面为大值H
        NSArray *sizeAry = [newRegex componentsSeparatedByString:@","];
        sizeValue = [NSValue valueWithCGSize:CGSizeMake([sizeAry.firstObject integerValue], [sizeAry.lastObject integerValue])];
        
        [JYVerifyRegEx.shareInstance.contentSizeCaChe setObject:sizeValue forKey:regEx];
    }
    
    
    return [sizeValue CGSizeValue];
}


/**
 校验输入的字符串是否合法

 @param input 待校验的字符串
 @param regEx 正则表达式
 @return 是否合法
 */
+ (BOOL)verifyInputString:(NSString *)input regEx:(NSString *)regEx {
    
    if (input == nil || regEx == nil) {
        return NO;
    }
//    NSRegularExpression *regExp = [JYVerifyRegEx.shareInstance.regExCaChe objectForKey:regEx];
//    if (!regExp) {
//        NSError *error = NULL;
//        regExp = [NSRegularExpression regularExpressionWithPattern:regEx options:(NSRegularExpressionCaseInsensitive) error:&error];
//        [JYVerifyRegEx.shareInstance.regExCaChe setObject:regExp forKey:regEx];
//        DebugLog(@"%@", regExp);
//    }
//    NSArray *result = [regExp matchesInString:input options:(NSMatchingReportProgress) range:NSMakeRange(0, input.length)];
//    return result.count;
    
    NSPredicate *regextestmobile = [NSPredicate predicateWithFormat:@"SELF MATCHES %@", regEx];
    BOOL evaluate = [regextestmobile evaluateWithObject:input];
    return evaluate;
}


- (NSString *)p_reverseRegExCache:(NSString *)regEx {
    
    NSString *reverseRegEx = [self.reverseRegExCaChe objectForKey:regEx];
    if (reverseRegEx == nil) {
        NSMutableString *tmp = [NSMutableString stringWithCapacity:regEx.length];
        // 1.先全部倒置，
        [regEx
         enumerateSubstringsInRange:NSMakeRange(0, regEx.length)
         options:(NSStringEnumerationByComposedCharacterSequences | NSStringEnumerationReverse)
         usingBlock:^(NSString * _Nullable substring, NSRange substringRange, NSRange enclosingRange, BOOL * _Nonnull stop) {
             
             [tmp appendString:substring];
             NSLog(@"substring:%@ substringRange:%@", substring, NSStringFromRange(substringRange));
         }];
        reverseRegEx = [tmp copy];
        [self.reverseRegExCaChe setObject:reverseRegEx forKey:regEx];
    }
    return reverseRegEx;
}

@end
